/*
 * Copyright (c) 2010 Andy Aspell-Clark
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */
package uk.org.aspellclark.agenedb;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.openintents.intents.AboutIntents;
import org.openintents.intents.FileManagerIntents;
import org.tc33.jenigma.Enigma;
import org.tc33.jenigma.components.Plugboard;
import org.tc33.jenigma.components.Reflector;
import org.tc33.jenigma.components.Rotor;

import uk.org.aspellclark.agenedb.view.EditPreferences;
import uk.org.aspellclark.agenedb.view.GedcomFileInformationView;
import uk.org.aspellclark.agenedb.view.GedcomTreeView;
import uk.org.aspellclark.agenedb.view.individual.IndividualDetailsView;
import uk.org.aspellclark.agenedb.view.individual.IndividualListRowAdapter;
import uk.org.aspellclark.common.CommonFunctions;
import uk.org.aspellclark.gedcom.GedcomParser;
import uk.org.aspellclark.gedcom.controller.Db4oController;
import uk.org.aspellclark.gedcom.controller.IndividualController;
import uk.org.aspellclark.gedcom.model.records.IndividualRecord;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class AGeneDb extends Activity implements OnItemClickListener {

	private static final String LAUNCHPAD_TRANSLATOR_CREDITS_SEPARATOR = ";";
	private static final String LAUNCHPAD_TRANSLATOR_CREDITS_REGEX = "(" + LAUNCHPAD_TRANSLATOR_CREDITS_SEPARATOR
			+ " )|(" + LAUNCHPAD_TRANSLATOR_CREDITS_SEPARATOR + ")";
	private static final String LAUNCHPAD_TRANSLATOR_CREDITS_HEADER = "Launchpad Contributions: ";
	private static final String LAUNCHPAD_TRANSLATOR_CREDITS_TAG = "translator-credits";

	private static final String PREFS_NAME = "AGeneDBPrefs";
	private static final int REQUEST_CODE_PICK_FILE_OR_DIRECTORY = 1;
	private static final int ID_DIALOG_PROGRESS_IMPORT = 987;
	private static final int ID_DIALOG_PROGRESS_POPULATE_LIST = 988;

	private static String gedcomFileDirectory = "gedcom";
	private static String gedcomImageFileDir = "images";

	private static String LOG_TAG = "AGeneDB";

	private final static String DB4OFILENAME = "AGeneDB.db4o";

	public static String getGedomImagePathDir() {
		final File extDir = Environment.getExternalStorageDirectory();
		return extDir.getPath() + File.separator + AGeneDb.gedcomFileDirectory + File.separator + gedcomImageFileDir
				+ File.separator;
	}

	public static String getGedomPathDir() {
		final File extDir = Environment.getExternalStorageDirectory();
		return extDir.getPath() + File.separator + AGeneDb.gedcomFileDirectory + File.separator;
	}

	private String dbFilename = "";

	private String extDirStr;

	private ProgressDialog loadingDialog;
	public final Handler handler = new Handler() {
		@Override
		public void handleMessage(final Message msg) {
			AGeneDb.this.loadingDialog.setProgress(msg.what);
		}
	};

	private Db4oController dbCntrlr;

	/**
	 * @return
	 */
	private String getPayPalDonateName() {
		return "AGeneDB";
	}

	private void getUserInputForDonatorCode() {
		AlertDialog.Builder alert = new AlertDialog.Builder(this);

		class UserResponse {
			boolean merge = false;
		}
		final UserResponse userResp = new UserResponse();

		alert.setTitle("Enter Donator Code");
		alert.setMessage("Please enter the donator code that was emailed to you");

		// Set an EditText view to get user input   
		final EditText input = new EditText(this);
		alert.setView(input);

		alert.setPositiveButton("Done", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int whichButton) {
				Preferences.donatedCheckString = input.getText().toString();
				AGeneDb.this.isRegistered();
			}
		});

		alert.show();
	}

	private boolean getUserInputForMergeData() {
		AlertDialog.Builder alert = new AlertDialog.Builder(this);

		class UserResponse {
			boolean merge = false;
		}
		final UserResponse userResp = new UserResponse();

		alert.setTitle("Merge Imported Data");
		alert.setMessage("Do you want to merge the imported data into the current family tree?");

		// Set an EditText view to get user input   
		//final EditText input = new EditText(this);  
		//alert.setView(input);  

		alert.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int whichButton) {
				userResp.merge = true;
			}
		});

		alert.setNegativeButton("No", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int whichButton) {
				userResp.merge = false;
			}
		});

		alert.show();
		return userResp.merge;
	}

	/**
	 * this method displays a progress dialog while it is performing the 'Long
	 * Process' of importing the gedcom file
	 */
	private void importGedcomFile(final String gedcomFname) {

		final File gedcomFile = new File(gedcomFname);
		if (gedcomFile.length() > (Preferences.MAX_GEDCOM_SIZE_UNREGISTERED * 1024)) {
			String str = this.getString(R.string.unregisteredCopyFileTooBig, Preferences.MAX_GEDCOM_SIZE_UNREGISTERED);
			Toast.makeText(AGeneDb.this, str, Toast.LENGTH_LONG).show();
			return;
		}

		//FIXME: finish this : boolean mergeData = this.getUserInputForMergeData();

		this.showDialog(ID_DIALOG_PROGRESS_IMPORT);

		if (!gedcomFile.exists()) {
			Toast.makeText(AGeneDb.this, R.string.fileNotFound, Toast.LENGTH_LONG).show();
			return;
		}
		Preferences.gedcomFilename = gedcomFname;
		final GedcomParser gedcomParser = new GedcomParser();
		gedcomParser.initialise(this.dbFilename, false);

		final Thread importGedcomFileThread = new Thread() {
			@Override
			public void run() {
				// *** Your Long Calculation (Or Other) Goes Here

				try {
					gedcomParser.parse(Preferences.gedcomFilename, AGeneDb.this.handler);

				} catch (final Exception e) {
					Log.e(LOG_TAG, e.getMessage());
					// Toast.makeText(AGeneDb.this, R.string.fileImportFailure,Toast.LENGTH_SHORT).show();
				}

				final Runnable updateListsAfterImport = new Runnable() {
					public void run() {
						AGeneDb.this.removeDialog(ID_DIALOG_PROGRESS_IMPORT);
						try {
							if (!gedcomParser.errors.isEmpty()) {
								Toast.makeText(AGeneDb.this, R.string.fileImportWithErrors, Toast.LENGTH_LONG).show();
								for (String msgStr : gedcomParser.errors) {
									Log.e("AGeneDB Gedcom Parsring Error", msgStr);
								}
							} else if (!gedcomParser.warnings.isEmpty()) {
								Toast.makeText(AGeneDb.this, R.string.fileImportWithWarnings, Toast.LENGTH_LONG).show();
							} else {
								Toast.makeText(AGeneDb.this, R.string.fileImportSuccess, Toast.LENGTH_SHORT).show();
							}
							AGeneDb.this.updateIndividualList();
							AGeneDb.this.preferencesSave(true);
						} catch (Throwable t) {
							//Store error and inform user!!
							Log.e(LOG_TAG, t.getMessage());
						}
						AGeneDb.this.setTitle("AGeneDB (" + Preferences.gedcomFilename + ")");
					}
				};
				// Run the thread
				AGeneDb.this.runOnUiThread(updateListsAfterImport);

				// *** Long Calculation ends here
				//handler.sendEmptyMessage(-1);
				//AGeneDb.this.dismissDialog(ID_DIALOG_PROGRESS);
			}
		};
		importGedcomFileThread.setName("GedcomImport");
		importGedcomFileThread.start();
	}

	private boolean isRegistered() {

		Rotor[] rotors = new Rotor[] { Rotor.ROTOR_I, Rotor.ROTOR_II, Rotor.ROTOR_III };
		char[] startPositions = new char[] { 'A', 'B', 'C' };
		Reflector reflector = Reflector.REFLECTOR_B;
		Plugboard plugboard = new Plugboard();
		plugboard.addCable('A', 'T');

		Enigma enigma = new Enigma(rotors, startPositions, plugboard, reflector);
		String plaintext = enigma.execute(Preferences.donatedCheckString);

		String ownersEmail = CommonFunctions.getOwnersEmailAddr(this);

		Log.d(LOG_TAG, ownersEmail);
		Log.d(LOG_TAG, plaintext);

		Preferences.isRegistered = (plaintext.equals(ownersEmail));
		if (Preferences.isRegistered) {
			Preferences.registeredTo = ownersEmail;
		}

		return true;
	}

	/**
	 * This is called after the user has selected a file in the file manager
	 * activity.
	 */
	@Override
	protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
		super.onActivityResult(requestCode, resultCode, data);

		switch (requestCode) {
		case REQUEST_CODE_PICK_FILE_OR_DIRECTORY:
			if (resultCode == RESULT_OK && data != null) {
				// obtain the filename
				Preferences.gedcomFilename = data.getDataString();
				if (Preferences.gedcomFilename != null) {
					// Get rid of URI prefix:
					if (Preferences.gedcomFilename.startsWith("file://")) {
						Preferences.gedcomFilename = Preferences.gedcomFilename.substring(7);
					}
					Preferences.gedcomFilename = Preferences.gedcomFilename.replace("%20", " ");
					this.importGedcomFile(Preferences.gedcomFilename);
				}
			}
			break;
		}
	}

	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);

		AGeneDb.this.dismissDialog(ID_DIALOG_PROGRESS_IMPORT);
		AGeneDb.this.removeDialog(ID_DIALOG_PROGRESS_IMPORT);

		AGeneDb.this.dismissDialog(ID_DIALOG_PROGRESS_POPULATE_LIST);
		AGeneDb.this.removeDialog(ID_DIALOG_PROGRESS_POPULATE_LIST);
	}

	/**
	 * Called when the activity is first created.
	 */
	@Override
	public void onCreate(final Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		this.setContentView(R.layout.individuals_list_view);

		if (this.isRegistered()) {
		}

		if (Preferences.firstTimeRound) {
			this.startActivity(new Intent(this.getBaseContext(), HtmlDialog.class));
			//		this.finish();
		}

		this.dbFilename = this.getDir("data", 0) + "/" + DB4OFILENAME;
		this.dbCntrlr = Db4oController.getInstance();
		this.dbCntrlr.dbFilename = this.dbFilename;
		//this.dbCntrlr.deleteDatabase();
		this.dbCntrlr.openDatabase();

		// check that OI file manager is installed. if not go to the market
		// so that the user can install it.
		final boolean fileAvailable = CommonFunctions.isIntentAvailable(this, FileManagerIntents.ACTION_PICK_FILE);
		if (!fileAvailable) {
			Intent marketLaunch = new Intent(Intent.ACTION_VIEW);
			String srchStr = "market://search?q=" + "org.openintents.filemanager";
			marketLaunch.setData(Uri.parse(srchStr));
			Toast.makeText(this, R.string.oifilemanager_pleaseinstall, Toast.LENGTH_SHORT).show();
			this.startActivity(marketLaunch);
		}

		this.extDirStr = AGeneDb.getGedomPathDir();
		//MultimediaController.getInstance().setGedomPathDir(this.extDirStr);

		try {
			this.dismissDialog(ID_DIALOG_PROGRESS_IMPORT);
			this.dismissDialog(ID_DIALOG_PROGRESS_POPULATE_LIST);
		} catch (Exception e) {
			Log.e(LOG_TAG, e.getMessage());
		}

		this.preferencesRestore();
		this.updateIndividualList();
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		this.loadingDialog = null;
		if (id == ID_DIALOG_PROGRESS_IMPORT) {
			this.loadingDialog = new ProgressDialog(this);
			this.loadingDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
			this.loadingDialog.setTitle(this.getString(R.string.PleaseWait));
			this.loadingDialog.setMessage(this.getString(R.string.LoadingGedcomFile));
			this.loadingDialog.setIndeterminate(false);
			this.loadingDialog.setCancelable(true);
			File f = new File(Preferences.gedcomFilename);
			this.loadingDialog.setMax((int) f.length());
			this.loadingDialog.setProgress(0);
			return this.loadingDialog;
		}
		if (id == ID_DIALOG_PROGRESS_POPULATE_LIST) {
			this.loadingDialog = new ProgressDialog(this);
			this.loadingDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
			this.loadingDialog.setTitle(this.getString(R.string.PleaseWait));
			this.loadingDialog.setMessage(this.getString(R.string.LoadingListItems));
			this.loadingDialog.setIndeterminate(true);
			this.loadingDialog.setCancelable(true);
			return this.loadingDialog;
		}

		return super.onCreateDialog(id);
	}

	@Override
	public boolean onCreateOptionsMenu(final Menu menu) {
		final boolean retValue = super.onCreateOptionsMenu(menu);
		//this.theMenu = menu;
		new MenuInflater(this.getApplication()).inflate(R.menu.mainmenu, menu);
		return retValue;
	}

	@Override
	public void onItemClick(AdapterView<?> arg0, View childView, int arg2, long arg3) {
		TextView tmpView = (TextView) childView;
		String prsnName = tmpView.getText().toString();

		// get person id from string
		StringTokenizer tok = new StringTokenizer(prsnName, "[");
		String idStr = tok.nextToken();
		idStr = tok.nextToken();
		if (idStr.endsWith("]")) {
			idStr = idStr.substring(0, idStr.length() - 1);
		}

		AGeneDb.this.updateCurrentPerson(idStr);
	}

	/**
	 * this function is called when the user selects a menu item from the options
	 * menu.
	 */
	@Override
	public boolean onOptionsItemSelected(final MenuItem item) {
		boolean retvalue = false;
		if (item.getItemId() == R.id.menu_selectGedcomFile) {
			this.selectGedcomFile();
			retvalue = true;
		} else if (item.getItemId() == R.id.menu_aboutAGeneDB) {
			this.showAboutdialog();
			retvalue = true;
		} else if (item.getItemId() == R.id.menu_settings) {
			this.startActivity(new Intent(this.getBaseContext(), EditPreferences.class));
			//Toast.makeText(this, R.string.notImplementedYet, Toast.LENGTH_SHORT).show();
			retvalue = true;
		} else if (item.getItemId() == R.id.menu_gedcomFileInfo) {
			try {
				this.startActivity(new Intent(this.getBaseContext(), GedcomFileInformationView.class));
			} catch (Exception e) {
				e.printStackTrace();
			}
			retvalue = true;
		} else if (item.getItemId() == R.id.menu_help) {
			try {
				this.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(this
						.getString(R.string.about_website_userguide_url))));
			} catch (Exception e) {
				e.printStackTrace();
			}
			retvalue = true;
		} else if (item.getItemId() == R.id.menu_quit) {
			this.finish();
			retvalue = true;
		} else if (item.getItemId() == R.id.menu_donate) {
			try {
				String paypalLink = "https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=9G2LQH6GBQSLW&lc=GB&item_name="
						+ this.getPayPalDonateName()
						+ "&currency_code=GBP&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted";
				this.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(paypalLink)));
			} catch (final Exception e) {
				Log.e(LOG_TAG, e.getMessage());
			}
			retvalue = true;
		}
		return retvalue;
	}

	@Override
	protected void onPause() {
		try {
			this.dbCntrlr.closeDatabase();
			this.dismissDialog(ID_DIALOG_PROGRESS_IMPORT);
			this.dismissDialog(ID_DIALOG_PROGRESS_POPULATE_LIST);
		} catch (Exception e) {
			Log.e(LOG_TAG, e.getMessage());
		}
		this.preferencesSave(true);
		this.dbCntrlr.openDatabase();
		super.onPause();
	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		final boolean aboutAvailable = CommonFunctions.isIntentAvailable(this, AboutIntents.ACTION_SHOW_ABOUT_DIALOG);
		MenuItem item;
		item = menu.findItem(R.id.menu_aboutAGeneDB);
		item.setEnabled(aboutAvailable);

		final boolean fileAvailable = CommonFunctions.isIntentAvailable(this, FileManagerIntents.ACTION_PICK_FILE);
		item = menu.findItem(R.id.menu_selectGedcomFile);
		item.setEnabled(fileAvailable);

		return super.onPrepareOptionsMenu(menu);
	}

	private void preferencesRestore() {
		final SharedPreferences settings = this.getSharedPreferences(PREFS_NAME, 0);
		Preferences.donatedCheckString = settings.getString(EditPreferences.PREF_DONATED_STRING, "");
		Preferences.gedcomFilename = settings.getString(EditPreferences.PREF_LOAD_LAST_FILENAME, "");
		Preferences.currentIndividualId = settings.getString(EditPreferences.PREF_CURRENT_PERSON_ID, "");
		Preferences.firstTimeRound = settings.getBoolean(EditPreferences.PREF_FIRST_EXECUTION, true);

		this.preferencesSave(true);
	}

	private void preferencesSave(boolean closeSuccess) {
		// Save user preferences. We need an Editor object to
		// make changes. All objects are from android.context.Context
		final SharedPreferences settings = this.getSharedPreferences(PREFS_NAME, 0);
		final SharedPreferences.Editor editor = settings.edit();
		//editor.putBoolean(EditPreferences.PREF_DONATE_EMAIL_ADDRESS, donatorEmailAddress);
		editor.putBoolean(EditPreferences.PREF_FIRST_EXECUTION, false);
		editor.putBoolean(EditPreferences.PREF_CLOSED_SUCCESSFULLY, closeSuccess);
		editor.putString(EditPreferences.PREF_DONATED_STRING, Preferences.donatedCheckString);
		editor.putString(EditPreferences.PREF_LOAD_LAST_FILENAME, Preferences.gedcomFilename);
		editor.putString(EditPreferences.PREF_CURRENT_PERSON_ID, Preferences.currentIndividualId);

		// Don't forget to commit your edits!!!
		editor.commit();
	}

	/**
	 * this function starts the file picker activity.
	 */
	private void selectGedcomFile() {
		Intent filePickerIntent = new Intent(FileManagerIntents.ACTION_PICK_FILE);
		final Uri gedcomDirUri = Uri.fromFile(new File(this.extDirStr));
		filePickerIntent.setData(gedcomDirUri);

		// Set fancy title and button (optional)
		filePickerIntent.putExtra(FileManagerIntents.EXTRA_TITLE, this.getString(R.string.open_title));
		filePickerIntent.putExtra(FileManagerIntents.EXTRA_BUTTON_TEXT, this.getString(R.string.open_button));

		try {
			this.startActivityForResult(filePickerIntent, REQUEST_CODE_PICK_FILE_OR_DIRECTORY);
		} catch (final ActivityNotFoundException e) {
			// No compatible file manager was found.
			Toast.makeText(this, R.string.oifilemanager_installed, Toast.LENGTH_SHORT).show();
		}
	}

	/**
	 * Show an about dialog for this application.
	 */
	private void showAboutdialog() {
		try {

			final Intent aboutDlgIntnt = new Intent(AboutIntents.ACTION_SHOW_ABOUT_DIALOG);

			aboutDlgIntnt.putExtra(AboutIntents.EXTRA_PACKAGE_NAME, this.getPackageName());

			// Supply the image.
			/*
			 * //alternative 1: Put the image resId into the provider. Bitmap image =
			 * BitmapFactory.decodeResource(getResources(), R.drawable.icon);//lossy
			 * String uri = Images.Media.insertImage(getContentResolver(), image,
			 * getString(R.string.about_logo_title),
			 * getString(R.string.about_logo_description));
			 * intent.putExtra(AboutIntents.EXTRA_ICON_URI, uri);
			 */

			// alternative 2: Supply the image name and package.
			aboutDlgIntnt.putExtra(AboutIntents.EXTRA_ICON_RESOURCE, this.getResources().getResourceName(
					R.drawable.ic_menu_info_details));

			aboutDlgIntnt.putExtra(AboutIntents.EXTRA_APPLICATION_LABEL, this.getString(R.string.app_name));

			// Get the app version
			String version = "?";
			try {
				final PackageInfo pi = this.getPackageManager().getPackageInfo(this.getPackageName(), 0);
				version = pi.versionName;
			} catch (final PackageManager.NameNotFoundException e) {
				uk.org.aspellclark.common.logging.Logger.e("ShowAboutWithExtras", "Package name not found", e);
			}
			aboutDlgIntnt.putExtra(AboutIntents.EXTRA_VERSION_NAME, version);

			aboutDlgIntnt.putExtra(AboutIntents.EXTRA_COMMENTS, this.getString(R.string.about_comments));
			aboutDlgIntnt.putExtra(AboutIntents.EXTRA_COPYRIGHT, this.getString(R.string.about_copyright));
			aboutDlgIntnt.putExtra(AboutIntents.EXTRA_WEBSITE_LABEL, this.getString(R.string.about_website_label));
			aboutDlgIntnt.putExtra(AboutIntents.EXTRA_WEBSITE_URL, this.getString(R.string.about_website_url));
			aboutDlgIntnt
					.putExtra(AboutIntents.EXTRA_AUTHORS, this.getResources().getStringArray(R.array.about_authors));
			aboutDlgIntnt.putExtra(AboutIntents.EXTRA_DOCUMENTERS, this.getResources().getStringArray(
					R.array.about_documenters));

			// Create string array of translators from translated string from
			// Launchpad
			// or (for English) from the array.
			final String translatorsString = this.getString(R.string.about_translators);
			if (translatorsString.equals(LAUNCHPAD_TRANSLATOR_CREDITS_TAG)) {
				aboutDlgIntnt.putExtra(AboutIntents.EXTRA_TRANSLATORS, this.getResources().getStringArray(
						R.array.about_translators));
			} else {
				final String[] translatorsArray = translatorsString.replaceFirst(LAUNCHPAD_TRANSLATOR_CREDITS_HEADER, "")
						.split(LAUNCHPAD_TRANSLATOR_CREDITS_REGEX);
				aboutDlgIntnt.putExtra(AboutIntents.EXTRA_TRANSLATORS, translatorsArray);
			}

			aboutDlgIntnt
					.putExtra(AboutIntents.EXTRA_ARTISTS, this.getResources().getStringArray(R.array.about_helpers));

			// Supply resource name of raw resource that contains the license:
			aboutDlgIntnt.putExtra(AboutIntents.EXTRA_LICENSE_RESOURCE, this.getResources().getResourceName(
					R.raw.license_short));

			/*
			 * //Read in the license file as a big String BufferedReader in = new
			 * BufferedReader(new InputStreamReader(
			 * getResources().openRawResource(R.raw.license_short))); String license =
			 * ""; String line; try { while ((line = in.readLine()) != null) { // Read
			 * line per line. license += line + "\n"; } } catch (IOException e) {
			 * //Should not happen. e.printStackTrace(); }
			 * intent.putExtra(AboutIntents.EXTRA_LICENSE, license);
			 * intent.putExtra(AboutIntents.EXTRA_WRAP_LICENSE, false);
			 */

			// Start about activity. Needs to be "forResult" with requestCode>=0
			// because the About dialog may call elements from your Manifest by your
			// package name.
			this.startActivityForResult(aboutDlgIntnt, 0);

		} catch (final ActivityNotFoundException e) {
			Toast.makeText(this, R.string.oiabout_installed, Toast.LENGTH_SHORT).show();
		}
	}

	public void showTreeView() {
		Intent intnt = new Intent(this.getBaseContext(), GedcomTreeView.class);
		this.startActivity(intnt);
	}

	/**
	 * stores the currently selected person.
	 * 
	 * @param prsnId
	 */
	public void updateCurrentPerson(final String prsnId) {
		try {
			if (prsnId.length() > 0) {
				// update currently selected person
				//this.gedcomParser.gedcom.currentPrsnId = prsnId;
				//Preferences.currentIndividualId = prsnId;

				this.startActivity(new Intent(this.getBaseContext(), IndividualDetailsView.class));
			}
		} catch (final Exception e) {
			Log.e(LOG_TAG, e.getMessage());
		}
	}

	/**
	 * This function populates the individuals list with the data from the loaded
	 * gedcom file.
	 */
	private void updateIndividualList() {

		// start tracing to "/sdcard/updateIndividualList.trace"
		//Debug.startMethodTracing("updateIndividualList");

		this.showDialog(ID_DIALOG_PROGRESS_POPULATE_LIST);
		//ProgressDialog.show(AGeneDb.this, "", "Loading. Please wait...", true);

		final List<IndividualRecord> individs = new ArrayList<IndividualRecord>();

		final Thread updateListThread = new Thread() {
			@Override
			public void run() {
				// *** Your Long Calculation (Or Other) Goes Here

				IndividualController individualCntrlr = new IndividualController(AGeneDb.this.dbCntrlr);

				List<IndividualRecord> tmpIndivids = individualCntrlr.getIndividuals();
				for (IndividualRecord i : tmpIndivids) {
					individs.add(i);
				}
				if (individs.size() == 0) {
					IndividualRecord tmpInd = new IndividualRecord("");
					tmpInd.noIndividualsInDatabase = true;
					individs.add(tmpInd);
				}

				final Runnable updateListsAfterImport = new Runnable() {
					public void run() {

						IndividualListRowAdapter indivAdapter = new IndividualListRowAdapter(AGeneDb.this,
								R.layout.individuals_list_view_row, individs);

						ListView lstView = (ListView) AGeneDb.this.findViewById(R.id.individualsListView);
						//indivAdapter.sort(new IndividualSurnameNameComparator());
						lstView.setAdapter(indivAdapter);
						indivAdapter.notifyDataSetChanged();

						lstView.requestLayout();

						AGeneDb.this.dismissDialog(ID_DIALOG_PROGRESS_POPULATE_LIST);
						AGeneDb.this.removeDialog(ID_DIALOG_PROGRESS_POPULATE_LIST);
					}
				};
				// Run the thread
				AGeneDb.this.runOnUiThread(updateListsAfterImport);

				// *** Long Calculation ends here
				//handler.sendEmptyMessage(-1);
				//AGeneDb.this.dismissDialog(ID_DIALOG_PROGRESS);
			}
		};
		updateListThread.setName("updateList");
		updateListThread.start();

		//		} catch (Exception e) {
		//			Log.e(LOG_TAG, e.getMessage());
		//			//Toast.makeText(this, "Exception Caught creating Individuals List", Toast.LENGTH_SHORT).show();
		//		}

		// stop tracing
		//Debug.stopMethodTracing();
	}

}
